(import cassandra.*)
(deftemplate Ring (declare (from-class Ring)))
(deftemplate RingStatistics (declare (from-class RingStatistics)))
(deftemplate ColumnFamilyThreadPool (declare (from-class ColumnFamilyThreadPool)))
(deftemplate LoadBalance (declare (from-class LoadBalance)))
(deftemplate Emailer (declare (from-class Emailer)))
(deftemplate CassandraStarter (declare (from-class CassandraStarter)))
  
(defrule unbalancedRing    
    ?r <- (Ring (nodeNumber ?nn)) 
    ?rs <- (RingStatistics)
    (or      
     (Ring (orderedLoadList ?ll&:(>= (/ (?ll get (- (?ll size) 1)) (?ll get 0)) 2))) 
     (RingStatistics (nodeNumber ?rnn&:(<> ?nn ?rnn)))  
    )
    =>
    (add (new LoadBalance ?r))
    (modify ?rs (nodeNumber ?nn))
)

(defrule backingUpThreadPool
	 (ColumnFamilyThreadPool  {activeCount == 0 && pendingTask > 0} (name ?n) (ip ?ip))
	=>
    (add (new Emailer (str-cat "The thread " ?n " from node with ip " ?ip " is backing up tasks. Please check!") "HIGH"))
)

(defrule downNodes
    (Ring (downNodesStopNotPlanned ?dn&:(not (?dn isEmpty))))
	=>
    (add (new CassandraStarter ?dn))
    (add (new Emailer (str-cat "The node(s) with ip(s) " ?dn " have been successfully recovered after an incident.")))
)